package com.wechat.page.contact.profile;

import org.springframework.beans.factory.annotation.Autowired;

import com.swak.fx.support.AbstractPage;
import com.swak.fx.support.FXMLView;
import com.swak.fx.support.Toast.ToastConfig;
import com.swak.fx.support.ui.UI.Themes;
import com.swak.fx.support.ui.UIButton;
import com.swak.ui.Event;
import com.swak.utils.StringUtils;
import com.swak.utils.time.DateTimes;
import com.wechat.Cons;
import com.wechat.Cons.Menus;
import com.wechat.dto.ChatDTO;
import com.wechat.dto.ContactDTO;
import com.wechat.page.api.ContactApi;
import com.wechat.page.contact.card.ContactInfoComp;
import com.wechat.page.contact.misc.ProfileForm;

import javafx.beans.binding.Bindings;
import javafx.beans.property.LongProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;

/**
 * 联系人 - 设置
 * 
 * @author 618lf
 */
@FXMLView(title = "联系人 - 设置", value = "ContactProfilePage.fxml", css = "ContactProfilePage.css")
public class ContactProfilePage extends AbstractPage {

	private ContactInfoComp infoComp;
	private Pane placeholder;
	private ProfileForm profileForm;
	private UIButton button;

	@Autowired
	private ContactApi contactApi;

	public ContactProfilePage() {
		this.infoComp = this.NewComp(ContactInfoComp.class);
		this.placeholder = new Pane();
		this.profileForm = new ProfileForm();
		this.button = new UIButton("发送消息").Success();
	}

	@Override
	public void initializeParts() {
		super.initializeParts();

		// 用户信息
		this.addChild(this.infoComp.getRoot());
		GridPane.setConstraints(this.infoComp.getRoot(), 0, 0);
		GridPane.setHgrow(this.infoComp.getRoot(), Priority.NEVER);
		GridPane.setVgrow(this.infoComp.getRoot(), Priority.NEVER);
		GridPane.setHalignment(this.infoComp.getRoot(), HPos.CENTER);
		GridPane.setFillWidth(this.infoComp.getRoot(), false);
		GridPane.setMargin(this.infoComp.getRoot(), new Insets(0, 0, 20, 0));

		// 用户信息
		this.addChild(this.profileForm);
		GridPane.setConstraints(this.profileForm, 0, 1);
		GridPane.setHgrow(this.profileForm, Priority.NEVER);
		GridPane.setVgrow(this.profileForm, Priority.NEVER);
		GridPane.setHalignment(this.profileForm, HPos.CENTER);
		GridPane.setFillWidth(this.profileForm, false);
		GridPane.setMargin(this.profileForm, new Insets(0, 0, 20, 0));

		// 按钮
		this.addChild(this.button);
		GridPane.setConstraints(this.button, 0, 2);
		GridPane.setHgrow(this.button, Priority.NEVER);
		GridPane.setVgrow(this.button, Priority.NEVER);
		GridPane.setHalignment(this.button, HPos.CENTER);
		GridPane.setValignment(this.button, VPos.CENTER);

		// 占位
		this.addChild(this.placeholder);
		GridPane.setConstraints(this.placeholder, 0, 3);
		GridPane.setHgrow(this.placeholder, Priority.ALWAYS);
		GridPane.setVgrow(this.placeholder, Priority.ALWAYS);
	}

	@Override
	public void setupEventHandlers() {
		super.setupEventHandlers();
		this.registerRootClickToRequestFocusEvent_WithoutInput();
		this.button.setOnAction((e) -> {
			ContactDTO contact = this.contactProperty().get();
			this.$post(Event.of().setKey(Cons.Event_Menu_Toggle).setMessage(Menus.Chat));
			this.$post(Event.of().setKey(Cons.Event_Chat_Select).setMessage(ChatDTO.of()
					.setId(contact.getId()).setType(contact.getType()).setNickName(contact.getNickName())));
		});
	}

	@Override
	public void setupBindings() {
		super.setupBindings();
		this.infoComp.contactProperty().bind(this.contactProperty());
		this.infoComp.refreshProperty().bind(this.refreshProperty());
		this.profileForm.aliasProperty().bind(Bindings.createStringBinding(() -> {
			ContactDTO contact = this.contactProperty().get();
			return contact != null ? contact.getAlias() : StringUtils.EMPTY;
		}, this.contactProperty, this.refreshProperty));
		this.profileForm.remarksProperty().bind(Bindings.createStringBinding(() -> {
			ContactDTO contact = this.contactProperty().get();
			return contact != null ? contact.getRemarks() : StringUtils.EMPTY;
		}, this.contactProperty, this.refreshProperty));
	}

	@Override
	public void setupValueChangedListeners() {
		super.setupValueChangedListeners();
		this.profileForm.aliasEditProperty().addListener((ob, o, n) -> {
			this.$run(() -> this.saveContactAlias(n));
		});
		this.profileForm.remarksEditProperty().addListener((ob, o, n) -> {
			this.$run(() -> this.saveContactRemarks(n));
		});
	}

	private void saveContactAlias(String alias) {
		ContactDTO contact = this.contactProperty.get();
		if (StringUtils.equals(contact.getAlias(), alias)) {
			return;
		}
		this.contactApi.saveAlias(ContactDTO.of().setAlias(alias) // 设置备注名
				.setId(contact.getId())).whenComplete((r, e) -> {
					this.postSave(r, e);
				});
	}

	private void saveContactRemarks(String remarks) {
		ContactDTO contact = this.contactProperty.get();
		if (StringUtils.equals(contact.getRemarks(), remarks)) {
			return;
		}
		this.contactApi.saveRemarks(ContactDTO.of().setRemarks(remarks).setId(contact.getId())).whenComplete((r, e) -> {
			this.postSave(r, e);
		});
	}

	private void postSave(ContactDTO contact, Throwable e) {
		if (e == null) {

			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug("[联系人属性] - 发送事件 ：{}", Cons.Event_Contact_Refresh);
				LOGGER.debug("[联系人属性] - 发送事件 ：{}", Cons.Event_Chat_Refresh);
			}

			this.$toast(ToastConfig.of().setMessage("修改成功").setTheme(Themes.Success)).show();
			this.$post(Event.of().setKey(Cons.Event_Contact_Refresh).setMessage(contact));
			this.$post(Event.of().setKey(Cons.Event_Chat_Refresh).setMessage(ChatDTO.of().setId(contact.getId())));
		} else {
			this.$toast(ToastConfig.of().setMessage("修改失败").setTheme(Themes.Error)).show();
		}
		this.$runUI(() -> {
			this.refreshProperty().set(DateTimes.nowMilli());
		});
	}

	// ================================================================================
	// Properties
	// ================================================================================
	private final ObjectProperty<ContactDTO> contactProperty = new SimpleObjectProperty<>();

	public ObjectProperty<ContactDTO> contactProperty() {
		return contactProperty;
	}

	private final LongProperty refreshProperty = new SimpleLongProperty();

	public LongProperty refreshProperty() {
		return refreshProperty;
	}
}
